package com.xjnt.base.support.admin.interceptor;

import java.sql.Timestamp;

import javax.servlet.http.HttpServletRequest;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.JFinal;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Logger;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.xjnt.base.support.admin.entity.Account;
import com.xjnt.base.support.admin.entity.Log;
import com.xjnt.base.support.admin.service.LogService;
import com.xjnt.frameworks.core.BaseController;
import com.xjnt.frameworks.exception.BusinessException;
import com.xjnt.frameworks.web.message.RetMsg;

public class ExceptionAndLogInterceptor implements Interceptor {

	private static final Logger logger = Logger.getLogger(ExceptionAndLogInterceptor.class);

	@Override
	public void intercept(Invocation inv) {
		try {
			inv.invoke();
		} catch (Exception ex) {
			exProcess(inv, ex);
		}
	}

	private void exProcess(Invocation inv, Exception ex) {
		String bizName = inv.getControllerKey();
		String remark = formatException(ex);
		HttpServletRequest request = inv.getController().getRequest();
		if (isAjax(request)) {
			RetMsg retMsg = new RetMsg();
			if (ex instanceof BusinessException) {
				BusinessException bex = (BusinessException) ex;
				retMsg.pushError(bex.getName() + "," + remark);
				bizName = bex.getName();
			} else {
				retMsg.pushError(ex.getMessage());
			}
			inv.getController().renderJson(retMsg);
		} else {
			inv.getController().renderError(500);
		}

		// 记录异常/日志。
		LogService logService = inv.getController().enhance(LogService.class, Tx.class);
		Log log = new Log();
		log.set(Log.NAME, bizName);
		log.set(Log.ACTION, inv.getMethodName());
		log.set(Log.IPADDR, inv.getController().getRequest().getRemoteAddr());
		Account account = (Account) ((BaseController) inv.getController()).getCurrUser();
		log.set(Log.USERNAME, account == null ? "NONE" : account.getStr(Account.USERNAME));
		log.set(Log.REMARK, remark);
		log.set(Log.TYPE, "系统异常");
		log.set(Log.CREATETIME, new Timestamp(System.currentTimeMillis()));
		logService.save(log);
		
		if (JFinal.me().getConstants().getDevMode()) {
			logger.error("", ex);
		}
	}

	private boolean isAjax(HttpServletRequest request) {
		String requestType = request.getHeader("X-Requested-With");
		return (requestType != null && requestType.equalsIgnoreCase("XMLHttpRequest"));
	}

	/**
	 * 格式化异常信息，用于友好响应用户
	 * 
	 * @param e
	 * @return
	 */
	private static String formatException(Exception e) {
		String message = null;
		Throwable ourCause = e;
		while ((ourCause = e.getCause()) != null) {
			e = (Exception) ourCause;
		}
		// 一些常见异常提示
		// String eClassName = e.getClass().getName();
		if (e instanceof BusinessException || e instanceof RuntimeException) {
			message = e.getMessage();
			if (StrKit.isBlank(message)){
				message = e.toString();
			}
		} else {
			message = e.getMessage();
			if (StrKit.isBlank(message)){
				message = e.toString();
			}
		}

		// 获取默认异常提示
		if (StrKit.isBlank(message)) {
			message = "系统繁忙,请稍后再试";
		}
		// 替换特殊字符
		message = message.replaceAll("\"", "'");
		return message;
	}
}
